'use strict';

const path = require('path')
const fse = require('fs-extra')
const pkgDir = require('pkg-dir').sync
const pathExists = require('path-exists').sync
const npminstall = require('npminstall')
const { isObject } = require('@tangmen-cli-dev/utils')
const formatPath = require('@tangmen-cli-dev/format-path')
const { getDefaultRegistry, getNpmLastVersion } = require('@tangmen-cli-dev/get-npm-info')

class Package {
    constructor(options) {
        // 判断边界情况 如果没有传参 直接提示用户options不得为空
        if (!options) {
            throw new Error('Package类的options参数不能为空')
        }
        // 如果参数不是对象的话提示用户options必须是对象
        if (!isObject(options)) {
            throw new Error('Package类的options参数必须是对象')
        }
        // package的目标路径
        this.targetPath = options.targetPath
            // 缓存Package的路径
        this.storeDir = options.storeDir
            // package的名字
        this.packageName = options.packageName
            // package的version
        this.packageVersion = options.packageVersion
            // package的缓存目录前缀
        this.cacheFilePathPrefix = this.packageName.replace('/', '_')
    }

    // 准备(预检)阶段
    // 如果缓存package的路径目录不存在的话，我们用fs模块创建一个目录
    // 如果使用者传进来的版本参数是latest，那么我们就要调取API获取最新版本的信息
    async prepare() {
        if (this.storeDir && !pathExists(this.storeDir)) {
            fse.mkdirpSync(this.storeDir)
        }
        // 如果是最新版本的包
        if (this.packageVersion === 'latest') {
            // 就从远程获取最新的版本并赋值给变量 packageVersion
            this.packageVersion = await getNpmLastVersion(this.packageName)
        }
    }

    // 读取缓存路径
    get cacheFilePath() {
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`);
    }

    // 获取指定的缓存路径
    getSpecificCacheFilePath(packageVersion) {
        return path.resolve(this.storeDir, `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`);
    }

    // 判断当前的package是否存在
    async exists() {
        // 判断当前的文件是使用缓存的模式还是直接使用的targetPath
        if (this.storeDir) {
            await this.prepare()
            return pathExists(this.cacheFilePath)

        } else {
            return pathExists(this.targetPath)
        }
    }

    // 安装package
    async install() {
        await this.prepare()
        return npminstall({
            root: this.targetPath,
            storeDir: this.storeDir,
            registry: getDefaultRegistry(),
            pkgs: [{
                name: this.packageName,
                version: this.packageVersion
            }]
        })
    }

    // 更新package
    async update() {
        await this.prepare()
        const latestPackageVersion = await getNpmLastVersion(this.packageName)
        const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion)
        if (!pathExists(latestFilePath)) {
            await npminstall({
                root: this.targetPath,
                storeDir: this.storeDir,
                registry: getDefaultRegistry(),
                pkgs: [{
                    name: this.packageName,
                    version: latestPackageVersion
                }]
            })
            this.packageVersion = latestPackageVersion
        } else {
            this.packageVersion = latestPackageVersion
        }
    }

    // 获取入口文件的路径
    async getRootFilePath() {
        function _getRootFile(targetPath) {
            // 1.获取package.json所在目录
            const dir = pkgDir(targetPath)
            if (dir) {
                // 2.读取package.json
                const pkgFile = require(path.resolve(dir, 'package.json'))
                    // 3.寻找main/lib
                if (pkgFile && pkgFile.main) {
                    return formatPath(path.resolve(dir, pkgFile.main))
                }
            }
            return null
        }
        if (this.storeDir) {
            return _getRootFile(this.cacheFilePath)
        } else {
            return _getRootFile(this.targetPath)
        }
    }

}

module.exports = Package